
from datetime import datetime
from flask import jsonify, request
from flask_login import current_user
from flask_restful import Resource, marshal_with, reqparse  # type: ignore
from controllers.errors.error import HTTPNotLoginError
from controllers.errors.fversion_errors import HTTPFVerTaskNotFoundError, HTTPFirewareNotExsitError, HTTPFirewareParamsError
from core.roles.role_check import check_perms
from libs.exception import BaseHTTPException
from libs.helper import StrBool, StrBoolNone, extract_remote_ip,DatetimeString, uuid_value
from libs.login import login_required
from controllers.console import api
from models.robot.rob_version import FVerTaskStatus
from models.robot.robots import AgentType
from werkzeug.exceptions import InternalServerError
from services.errors.account import NotLoginError
from services.errors.versiions import FVerTaskNotExistError, FirewareParamsError, FirewareVersionNotExistError
from services.ota.fver_service import FVerService
# from services.robot.version_service import VersionService
from fields.robot.version_fields_def import fver_fields,fver_task_fields,fver_list_fields,fver_task_result_list_fields

# class HardwareVersionApi(Resource):
#     @login_required
#     @check_role(base_role=AccountRole.NORMAL_USER)
#     @marshal_with(hardware_ver_fields)
#     def get(self):
#         parser = reqparse.RequestParser()
#         parser.add_argument('hardware_version',type=str,required=False,location='args')
#         parser.add_argument('start',type=DatetimeString("%Y-%m-%d %H:%M"),required=False,location='args')
#         parser.add_argument('end',type=DatetimeString("%Y-%m-%d %H:%M"),required=False,location='args')
#         # parser.add_argument('is_force',type=StrBool,required=False,default=None,location='args')
#         # parser.add_argument('page',type=int,required=False,default=-1,location='args')
#         # parser.add_argument('page_size',type=int,required=False,default=-1,location='args')
#         args = parser.parse_args()
#         return VersionService.get_h_ver_list(current_user,args)
    
#     @login_required
#     @check_role(base_role=AccountRole.TENANT_ADMIN)
#     @marshal_with(hardware_ver_fields)
#     def post(self):
#         parser = reqparse.RequestParser()
#         parser.add_argument('hardware_version',type=str,required=True,location='json')
#         parser.add_argument('descrip',type=str,required=True,location='json')
#         args = parser.parse_args()
#         ver = args.get('hardware_version')
#         descrip = args.get('descrip')
#         try:
#             new_ver= VersionService.create_h_ver(current_user,ver,descrip,extract_remote_ip(request))
#             return new_ver
#         except NotLoginError:
#             raise HTTPNotLoginError()
#         except Exception as e:
#             raise BaseHTTPException(str(e))


#     @login_required
#     @check_role(base_role=AccountRole.TENANT_ADMIN)
#     def delete(self):
#         parser = reqparse.RequestParser()
#         parser.add_argument('id',type=str,required=True,location='json')
#         args = parser.parse_args()
#         ver_id = args.get('id')
#         try:
#             VersionService.del_h_ver(current_user,ver_id,extract_remote_ip(request))
#         except NotLoginError:
#             raise HTTPNotLoginError()
#         except Exception as e:
#             raise BaseHTTPException(str(e))
        

class FirewareVersionApi(Resource):
    @login_required
    @check_perms(perms=['fireware_version:list'])
    @marshal_with(fver_list_fields)
    def get(self):
        parser = reqparse.RequestParser()
        parser.add_argument('ver',type=str,required=False,default=None,location='args')
        parser.add_argument('agent_type',type=str,required=False,default=None,location='args')
        parser.add_argument('is_new',type=StrBoolNone,required=False,default=None,location='args')
        parser.add_argument('page',type=int,required=False,default=-1,location='args')
        parser.add_argument('page_size',type=int,required=False,default=-1,location='args')
        args = parser.parse_args()
        ver = args.get("ver",None)
        agent_type = args.get("agent_type",None)
        if agent_type:
            if agent_type not in AgentType.choices():
                return []
        is_new = args.get("is_new",None)
        page = args.get("page",-1)
        page_size = args.get("page_size",-1)
        try:
            return FVerService.get_fver_list(current_user.current_tenant_id,
                                         ver,agent_type,is_new,page,page_size)
        except Exception as e:
            raise InternalServerError(str(e))
        
    
    
    @login_required
    @check_perms(perms=['fireware_version:new'])
    @marshal_with(fver_fields)
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('ver',type=str,required=True,location='json')
        parser.add_argument('md5',type=str,required=False,location='json')
        parser.add_argument('file_id',type=str,required=False,location='json')
        parser.add_argument('file_url',type=str,required=False,location='json')
        parser.add_argument('agent_type',type=str,choices=AgentType.choices(),required=True,location='json')
        parser.add_argument('is_new',type=StrBool,required=True,location='json')
        parser.add_argument('descrip',type=str,required=True,location='json')
        args = parser.parse_args()
        try:
            return FVerService.create_fver(current_user,args,extract_remote_ip(request))
        except NotLoginError:
            raise HTTPNotLoginError()
        except FirewareParamsError as e:
            raise HTTPFirewareParamsError(e.description)
        except Exception as e:
            raise BaseHTTPException(str(e))
        
    

    @login_required
    @check_perms(perms=['fireware_version:update'])
    @marshal_with(fver_fields)
    def put(self):
        parser = reqparse.RequestParser()
        parser.add_argument('id',type=str,required=False,location='json')
        parser.add_argument('ver',type=str,required=False,location='json')
        parser.add_argument('md5',type=str,required=False,location='json')
        parser.add_argument('file_id',type=str,required=False,location='json')
        parser.add_argument('file_url',type=str,required=False,location='json')
        parser.add_argument('agent_type',type=str,choices=AgentType.choices(),required=True,location='json')
        parser.add_argument('is_new',type=StrBool,required=True,location='json')
        parser.add_argument('descrip',type=str,required=True,location='json')
        args = parser.parse_args()
        try:
            return FVerService.update_fver(current_user,args,extract_remote_ip(request))
        except NotLoginError:
            raise HTTPNotLoginError()
        except FirewareParamsError as e:
            raise HTTPFirewareParamsError(e.description)
        except Exception as e:
            raise BaseHTTPException(str(e))


    @login_required
    @check_perms(perms=['fireware_version:del'])
    def delete(self):
        parser = reqparse.RequestParser()
        parser.add_argument('id',type=str,required=True,location='json')
        args = parser.parse_args()
        ver_id = args['id']
        try:
            FVerService.delete_fver(current_user,ver_id,extract_remote_ip(request))
        except FirewareVersionNotExistError as e :
            raise HTTPFirewareNotExsitError(e.fver_id)
        except FirewareParamsError as e:
            raise HTTPFirewareParamsError(e.description)
        except Exception as e:
            raise BaseHTTPException(str(e))
        
class FVerDetailApi(Resource):
    @login_required
    @check_perms(perms=['fireware_version:read'])
    @marshal_with(fver_fields)
    def get(self,fver_id):
        try:
            fver = FVerService.get_fver_by_id(fver_id)
            if not fver:
                raise HTTPFirewareNotExsitError(fver_id)
            return fver
        except HTTPFirewareNotExsitError as e:
            raise e
        except Exception as e:
            raise InternalServerError(str(e))
        
class FverStatisticApi(Resource):
    @login_required
    @check_perms(perms=['fireware_version:list'])
    def get(self,fver_id):
        try:
            return FVerService.get_fver_statistic_by_id(fver_id)
        except FirewareVersionNotExistError as e:
            raise HTTPFirewareNotExsitError(e.fver_id)
        except Exception as e:
            raise InternalServerError(str(e))

class FVerTaskApi(Resource):
    @login_required
    @check_perms(perms=['fireware_task:list'])
    @marshal_with(fver_task_fields)
    def get(self):
        parser = reqparse.RequestParser()
        parser.add_argument("id",type=int,required=False,location='args')
        parser.add_argument("name",type=str,required=False,location='args')
        parser.add_argument("fver_id",type=str,required=False,location='args')
        parser.add_argument('start',type=DatetimeString("%Y-%m-%d %H:%M"),required=False,location='args')
        parser.add_argument('end',type=DatetimeString("%Y-%m-%d %H:%M"),required=False,location='args')
        parser.add_argument('include_del',type=StrBoolNone,default=False,location='args')
        args = parser.parse_args()
        try:
            return FVerService.get_fver_tasks(args)
        except Exception as e:
            raise InternalServerError(str(e))
    
    @login_required
    @check_perms(perms=['fireware_task:new'])
    @marshal_with(fver_task_fields)
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument("name",type=str,required=True,location='json')
        parser.add_argument("fver_id",type=uuid_value,required=True,location='json')
        parser.add_argument("remark",type=str,required=False,location='json')
        parser.add_argument('robot_ids',type=str,action='append',required=False,location='json')
        parser.add_argument('reservation_at',DatetimeString("%Y-%m-%d %H:%M"),required=False,location='json')
        args = parser.parse_args()
        name = args["name"]
        fver_id = args["fver_id"]
        remark = args.get("remark")
        robot_ids = args.get("robot_ids",[])
        reservation_at = args.get("reservation_at",None)
        if not reservation_at:
            reservation_at = datetime.now()
        try:
            return FVerService.create_task(current_user,fver_id,name,remark,robot_ids,reservation_at,extract_remote_ip(request))
        except Exception as e:
            raise InternalServerError(str(e))
        
    @login_required
    @check_perms(perms=['fireware_task:del'])
    def delete(self):
        parser = reqparse.RequestParser()
        parser.add_argument('id', type=str, required=True, location='json')
        args = parser.parse_args()
        task_id = args['id']
        try:
            stop_count = FVerService.delete_fver_task(current_user,task_id,extract_remote_ip(request))
            return jsonify({"code": 200, "message": "success","stop_count":stop_count})
        except FVerTaskNotExistError as e:
            raise HTTPFVerTaskNotFoundError(e.task_id)
        except Exception as e:
            raise InternalServerError(str(e))


class FVerTaskDetailApi(Resource):
    @login_required
    @check_perms(perms=['fireware_task:list'])
    @marshal_with(fver_task_fields)
    def get(self,task_id):
        try:
            fver = FVerService.get_fver_task_by_id(task_id)
            if not fver:
                raise HTTPFVerTaskNotFoundError(task_id)
            return fver
        except HTTPFVerTaskNotFoundError as e:
            raise e
        except Exception as e:
            raise InternalServerError(str(e))
        

class FVerTaskResultsApi(Resource):
    @login_required
    @check_perms(perms=['fireware_task:list'])
    @marshal_with(fver_task_result_list_fields)
    def get(self,task_id):
        parser=reqparse.RequestParser()
        parser.add_argument('robot_id',type=str,required=False,default=None,location='args')
        parser.add_argument("status",type=str,required=False,default=None,location='args')
        parser.add_argument('page',type=int,required=False,default=-1,location='args')
        parser.add_argument('page_size',type=int,required=False,default=-1,location='args')
        args = parser.parse_args()
        status = args.get('status',None)
        if status and status.upper() not in FVerTaskStatus.choices():
            status = None
        elif status:
            status = status.upper()
        page = args.get('page',-1)
        page_size = args.get('page_size',-1)
        robot_id = args.get('robot_id',None)
        try:
            return FVerService.get_fver_task_results_by_id(task_id,status,robot_id,page,page_size)
        except FVerTaskNotExistError as e:
            raise HTTPFVerTaskNotFoundError(e.task_id)
        except Exception as e:
            raise InternalServerError(str(e))
class FverTaskStatisticApi(Resource):
    @login_required
    @check_perms(perms=['fireware_task:list'])
    def get(self,task_id):
        try:
            return FVerService.get_fver_task_statistic_by_id(task_id)
        except FVerTaskNotExistError as e:
            raise HTTPFVerTaskNotFoundError(e.task_id)
        except Exception as e:
            raise InternalServerError(str(e))
        
api.add_resource(FirewareVersionApi, '/fvers')
api.add_resource(FVerTaskApi, '/fvers/tasks')
api.add_resource(FVerDetailApi,'/fvers/detail/<string:fver_id>')
api.add_resource(FverStatisticApi,'/fvers/statistic/<string:fver_id>')
api.add_resource(FVerTaskDetailApi,'/fvers/task/detail/<string:task_id>')
api.add_resource(FverTaskStatisticApi,'/fvers/task/statistic/<string:task_id>')
api.add_resource(FVerTaskResultsApi,'/fvers/task/<string:task_id>/results')